package cn.virens.web.controller;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.virens.Assert;
import cn.virens.common.CloseableUtil;
import cn.virens.common.RequestUtil;
import cn.virens.database.mysql.model.web.WebPage;
import cn.virens.service.inter.web.WebPageService;
import cn.virens.web.common.BaseJSONController;
import cn.virens.web.components.spring.exception.NotFileFoundException;

@RestController
public class WebPageContorller extends BaseJSONController {
	private final static SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");

	private @Autowired WebPageService mWebPageService;

	@RequestMapping(path = "/web/view/*")
	public void view0(HttpServletRequest request, HttpServletResponse response) throws IOException {
		response.sendRedirect(request.getRequestURI() + "/index.html");
	}

	@RequestMapping(path = "/web/view/{code}/**/*")
	public void view(@PathVariable String code, HttpServletRequest request, HttpServletResponse response) throws IOException {
		OutputStream outputStream = null;
		InputStream inputStream = null;

		try {
			// 查询活动信息
			WebPage record = mWebPageService.selectOne(code);
			if (record == null) { throw new NotFileFoundException("File", code); }

			// 获取活动存储根目录
			String rootPath = getRootPath(request);
			String targetPath = record.getPath(rootPath);

			// 获取当前请求文件
			String uri = request.getRequestURI();
			String name = uri.replaceFirst("/web/view/" + code, "");

			// 获取资源文件
			File file = new File(targetPath, name);
			if (!file.exists()) { throw new NotFileFoundException("File", code); }

			// 重置应答头
			response.reset();
			response.setHeader("Web-Page-Time", getTime(record));
			response.setHeader("Web-Page-Name", getName(record));
			response.setHeader("Web-Page-File", FileUtil.getName(name));
			response.setHeader("Content-Type", FileUtil.getMimeType(name));

			// 获取输入*输出流
			inputStream = FileUtil.getInputStream(file);
			outputStream = response.getOutputStream();

			// 文件流输出
			int len = 0;
			byte[] buffer = new byte[1024];
			while ((len = inputStream.read(buffer)) != -1) {
				outputStream.write(buffer, 0, len);
			}
		} catch (NotFileFoundException e) {
			response.sendError(404, e.getMessage());
		} catch (IOException e) {
			response.sendError(500, e.getMessage());
		} finally {
			CloseableUtil.close(inputStream);
			CloseableUtil.close(outputStream);
		}
	}

	@RequestMapping(path = "/web/upload.json", method = { RequestMethod.POST, RequestMethod.OPTIONS })
	public void uploadOptions(HttpServletRequest request, HttpServletResponse response) {
		String origin = StrUtil.emptyToDefault(request.getHeader(HttpHeaders.ORIGIN), "*");

		response.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "GET,POST,OPTIONS");
		response.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
		response.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, origin);
		response.setHeader(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "86400");
	}

	@RequestMapping(path = "/web/upload.json", method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
	public Model upload(@RequestParam("file") MultipartFile file, HttpServletRequest request, HttpServletResponse response, Model model) {
		this.uploadOptions(request, response);

		ZipEntry entry = null;
		ZipInputStream zipIn = null;
		try {
			Assert.isNull(file, "文件不存在");

			// 获取存储目录
			String rootPath = getRootPath(request);
			String savePath = getRealPath(request);

			// 获取页面信息
			String code = DigestUtil.md5Hex(file.getBytes());
			String name = RequestUtil.getValueStr(request, "name");

			// 解压上传的ZIP包
			String targetStr = rootPath + savePath + code;
			zipIn = new ZipInputStream(file.getInputStream());
			while ((entry = zipIn.getNextEntry()) != null && !entry.isDirectory()) {
				File target = new File(targetStr, entry.getName());
				if (!target.getParentFile().exists()) {
					target.getParentFile().mkdirs();// 创建文件父目录
				}

				// 将zip内容解压到指定目录
				FileUtil.writeFromStream(zipIn, target);
			}

			// 关闭zip实例
			zipIn.closeEntry();

			// 保存页面信息
			WebPage record = new WebPage();
			record.setPath(savePath);
			record.setCode(code);
			record.setName(name);

			// 将活动页面信息保存到数据库
			if (mWebPageService.insert(record) != null) {
				return renderSuccess(record.getCode(), model, "发布成功");
			} else {
				return renderFail(model, "SaveErr", "发布失败");
			}
		} catch (Exception e) {
			return renderFail(model, e);
		} finally {
			CloseableUtil.close(zipIn);
		}
	}

	private static String getRootPath(HttpServletRequest request) {
		return request.getServletContext().getRealPath("/");
	}

	private static String getRealPath(HttpServletRequest request) {
		return "/upload/webpages/" + df.format(new Date()) + "/";
	}

	private static String getName(WebPage record) {
		return record.getName();
	}

	private static String getTime(WebPage record) {
		return df.format(record.getCreateTime());
	}
}
